package com.sds.service.impl;

import com.sds.service.AtomicityService;
import org.springframework.stereotype.Service;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class AtomicityServiceImpl implements AtomicityService {

    private final Object syncLock = new Object();
    private int syncCounter = 0;

    private AtomicInteger casCounter = new AtomicInteger(0);

    private ReentrantLock lock = new ReentrantLock();
    private int lockCounter = 0;

    private static ThreadLocal<String> tl1 = new ThreadLocal<>();
    private static ThreadLocal<String> tl2 = new ThreadLocal<>();

    /**
     * synchronized关键字
     */
    @Override
    public void synchronizedMethod() {
        synchronized (syncLock) {
            syncCounter++;
        }
    }

    /**
     * CAS（Compare and Swap）操作，即比较并交换
     * 如果内存位置的当前值与预期原值不相等，会放弃本次操作，并在一个循环中不断重试，直到成功为止。即自旋
     */
    @Override
    public void casMethod() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                casCounter.incrementAndGet();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                casCounter.incrementAndGet();
            }
        });
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("CAS counter: " + casCounter.get());
    }

    /**
     * Lock锁
     */
    @Override
    public void lockMethod() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                lock.lock();
                try {
                    lockCounter++;
                } finally {
                    lock.unlock();
                }
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                lock.lock();
                try {
                    lockCounter++;
                } finally {
                    lock.unlock();
                }
            }
        });
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Lock counter: " + lockCounter);

    }

    /**
     * ThreadLocal, 为每个线程提供独立的变量副本
     */
    @Override
    public void threadLocalMethod() {
        tl1.set("123");
        tl2.set("456");
        Thread t1 = new Thread(() -> {
            tl1.set("789");
            System.out.println("t1: " + tl1.get());
            System.out.println("t1: " + tl2.get());
        });
        t1.start();

        System.out.println("main: " + tl1.get());
        System.out.println("main: " + tl2.get());
    }
}